package org.kotboot.service

import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import org.kotboot.cons.ConsJwt
import org.kotboot.domain.User
import org.kotboot.enums.ESignType
import org.kotboot.exception.AuthFailedException
import org.kotboot.kit.*
import org.kotboot.module.JwtUser
import org.kotboot.module.R
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import javax.annotation.Resource


@Service
class SignServ(

        @Resource val userServ: UserServ,

        @Autowired val consJwt: ConsJwt,
        @Value(value = "\${app.login.aes.key.password}") val sessionKey :String,
        @Value(value = "\${app.login.aes.key.session}") val pwdKey :String

){

    val log: Logger = LoggerFactory.getLogger(SignServ::class.java)
    /**  
     * 登录操作
     *   
     * @author jisong.sun  
     * @date 18-4-28 下午5:08
     * @param   
     * @return 
     * @modify-by 
     */  
    fun signin(parm:KMap): R<*>{
        log.info("signin,param:{}",parm)
        val _session = parm.getString("_session")
        val decrypt:String? = AES.decrypt(_session, sessionKey)
        log.debug("_session , decrypt result:{}",decrypt)
        if(isNull(decrypt)){
            return R.ER("登录失败，参数错误")
        }
        val sesssionObj: JSONObject = JSON.parseObject(decrypt)
        log.debug("_session result map:{}",sesssionObj)
        val type:String? = parm.getStringSafe("type")
        return when (type){
            ESignType.MOB_PWD.name -> signin_pwd(sesssionObj)
            ESignType.MOB_SMS.name -> signin_sms(sesssionObj)
            else -> R.ER("不支持的登录类型")
        }
    }

    /**
     * 短信码登录
     *
     * @author jisong.sun
     * @date 18-4-28 下午5:07
     * @param
     * @return
     * @modify-by
     */
    private fun signin_sms(sesssionObj: JSONObject): R<*> {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    /**
     * 密码登录
     *
     * @author jisong.sun
     * @date 18-4-28 下午5:07
     * @param
     * @return
     * @modify-by
     */
    private fun signin_pwd(sesssionObj: JSONObject): R<*> {
        val mobile: String? = sesssionObj.getString("mobile")
        val password: String? = sesssionObj.getString("password")
        judgePwd(password)
        val user: User = userServ.findByMob(mobile) ?: return R.ER("会员不存在，可以注册新会员")
        val dbpwd:String = user.password
        val salt: String = user.salt
        val originCode = MD5.encoder16(password + salt)
        if(dbpwd != originCode){
            return R.ER("密码错误，请重试")
        }
        return doSignIn(user)
    }

    private fun judgePwd(encrypt_password: String?, encrypt_repassword: String? = "-1") {
        log.debug("")
        encrypt_password?:throw AuthFailedException("密码格式错误")
        val password: String? = AES.decrypt(encrypt_password, pwdKey)
        password?:throw AuthFailedException("密码不符合规则")
        if(password.length <30) throw AuthFailedException("密码不符合规则")
        val realPwd: String = password.substring(5).reversed().substring(6)
        if(realPwd.matches(Regex("^\\w{8,18}$")).not()){
            throw AuthFailedException("密码必须是8-18位字母，数字，下划线组合")
        }
        if("-1".equals(encrypt_password).not()){
            if(encrypt_password.equals(encrypt_repassword).not()){
                throw AuthFailedException("两次密码不一样")
            }
        }
    }

    /**
     *  执行登录操作，生成jwt code
     *
     * @author jisong.sun
     * @date 18-4-28 下午5:07
     * @param
     * @return
     * @modify-by
     */
    private fun doSignIn(user: User): R<*> {
        val jwtUser = JwtUser()
        jwtUser.userid = user.id
        jwtUser.nickname = user.nickname
        val subject: String = K.toJson(jwtUser)
        val create:String = consJwt.create(subject)
        val res = JSONObject()
        res.put("x-session",create)
        return R.OK("登录成功",res)
    }

    /**
     * 注册操作
     *
     * @author jisong.sun
     * @date 18-4-28 下午5:09
     * @param
     * @return
     * @modify-by
     */
    fun signup(param:KMap) :R<*> {
        val _session = param.getString("_session")
        val decrypt:String? = AES.decrypt(_session, sessionKey)
        if(isNull(decrypt)){
            return R.ER("注册失败，参数错误")
        }
        val sesssionObj: JSONObject = JSON.parseObject(decrypt)
        val type:String? = param.getStringSafe("type")
        val mobile:String = sesssionObj.getString("mobile")
        if(judgeMobile(mobile).not()) return R.ER("手机号码格式错误")
        val user:User? = userServ.findByMob(mobile)
        if(notNull(user)) return R.ER("手机号码已注册，请直接登录，或找回密码")
        return when (type){
            ESignType.MOB_PWD.name -> signup_pwd(sesssionObj)
            ESignType.MOB_SMS.name -> signup_sms(sesssionObj)
            else -> R.ER("不支持的注册类型")
        }
    }

    private fun signup_sms(sesssionObj: JSONObject): R<*> {
        val smscode:String = sesssionObj.getString("smscode")
        val mobile:String = sesssionObj.getString("mobile")

        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    private fun signup_pwd(sesssionObj: JSONObject): R<*> {
        val en_password: String? = sesssionObj.getString("password")
        val en_repassword: String? = sesssionObj.getString("repassword")
        val mobile:String = sesssionObj.getString("mobile")
        judgePwd(en_password,en_repassword)

        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }


    /**
     * 获取短信码
     *
     * @author jisong.sun
     * @date 18-4-28 下午5:09
     * @param
     * @return
     * @modify-by
     */
    fun smsCode(param: KMap):R<*> = R.OK()
}